<script setup lang="ts">
import type { Key } from 'ant-design-vue/es/vc-tree/interface';

import type { Nullable } from '@vben/types';

import type {
  ContextMenuItem,
  TreeActionItem,
  TreeActionType,
  TreeItem,
} from '#/components/tree';

import { h, onMounted, ref, unref } from 'vue';

import { PermModeEnum } from '@vben/access';

import {
  DeleteOutlined,
  EditOutlined,
  PlusSquareOutlined,
} from '@ant-design/icons-vue';
import { Button } from 'ant-design-vue';

import { DefAreaApi } from '#/api';
import { BasicTree } from '#/components/tree';
import { PermCode } from '#/enums/perm';
import { useMessage } from '#/hooks/web/useMessage';
import { $t } from '#/locales';
import { findNodeByKey } from '#/utils/helper/treeHelper';

defineOptions({
  name: 'DefAreaTree',
  inheritAttrs: false,
});

const emit = defineEmits<Emits>();

interface Emits {
  (e: 'select', parent: TreeItem, current: TreeItem): void;
  (e: 'add', parent: TreeItem): void;
  (e: 'edit', parent: TreeItem, current: TreeItem): void;
}

const { createMessage, createConfirm } = useMessage();

const treeRef = ref<Nullable<TreeActionType>>(null);
const treeData = ref<TreeItem[]>([]);
const treeLoading = ref<boolean>(false);
const permCode = PermCode.devOperation.system.defArea;

function getTree() {
  const treeR = unref(treeRef);
  if (!treeR) {
    throw new Error('树结构加载失败,请刷新页面');
  }
  return treeR;
}

onMounted(async () => {
  await fetch();
});

// 加载数据
async function fetch() {
  try {
    treeLoading.value = true;

    treeData.value = (await DefAreaApi.tree({})) as unknown as TreeItem[];

    setTimeout(() => {
      getTree().setCheckedKeys([]);
    }, 0);
  } finally {
    treeLoading.value = false;
  }
}

// 选择节点
function handleSelect(keys: Key[]) {
  if (keys[0]) {
    const node = findNodeByKey(keys[0], treeData.value);
    const parent = findNodeByKey(node?.parentId, treeData.value);

    emit('select', parent, node);
  }
}

// 悬停图标
const actionList: TreeActionItem[] = [
  {
    auth: [permCode.add],
    authMode: PermModeEnum.HasAny,
    render: (node) => {
      return h(PlusSquareOutlined, {
        class: 'ml-2',
        title: $t('common.title.add'),
        onClick: (e: Event) => {
          e?.stopPropagation();
          e?.preventDefault();
          emit('add', findNodeByKey(node.id as Key, treeData.value));
        },
      });
    },
  },
  {
    auth: [permCode.edit],
    authMode: PermModeEnum.HasAny,
    render: (node) => {
      return h(EditOutlined, {
        class: 'ml-2',
        title: $t('common.title.edit'),
        onClick: (e: Event) => {
          e?.stopPropagation();
          e?.preventDefault();
          const current = findNodeByKey(node?.id as Key, treeData.value);
          const parent = findNodeByKey(node?.parentId as Key, treeData.value);
          emit('edit', parent, current);
        },
      });
    },
  },
  {
    auth: [permCode.delete],
    authMode: PermModeEnum.HasAny,
    render: (node) => {
      return h(DeleteOutlined, {
        class: 'ml-2',
        title: $t('common.title.delete'),
        style: { color: '#ED6F6F' },
        onClick: (e: Event) => {
          e?.stopPropagation();
          e?.preventDefault();
          batchDelete([node.id as string]);
        },
      });
    },
  },
];

// 右键菜单
const getRightMenuList = (node: any): ContextMenuItem[] => {
  return [
    {
      label: $t('common.title.addChildren'),
      auth: [permCode.add],
      authMode: PermModeEnum.HasAny,
      handler: () => {
        emit('add', findNodeByKey(node.id as Key, treeData.value));
      },
      icon: 'ant-design:plus-outlined',
    },
    {
      label: $t('common.title.edit'),
      auth: [permCode.edit],
      authMode: PermModeEnum.HasAny,
      handler: () => {
        const current = findNodeByKey(node?.id as Key, treeData.value);
        const parent = findNodeByKey(node?.parentId as Key, treeData.value);
        emit('edit', parent, current);
      },
      icon: 'ant-design:edit-outlined',
    },
    {
      label: $t('common.title.delete'),
      auth: [permCode.delete],
      authMode: PermModeEnum.HasAny,
      handler: () => {
        batchDelete([node?.id as string]);
      },
      icon: 'ant-design:delete-outlined',
    },
  ];
};

// 点击树外面的 新增
function handleAdd() {
  emit('add', findNodeByKey('0', treeData.value));
}

// 执行批量删除
async function batchDelete(ids: string[]) {
  createConfirm({
    iconType: 'warning',
    content: '选中节点及其子结点将被永久删除, 是否确定删除？',
    onOk: async () => {
      try {
        await DefAreaApi.remove(ids);
        await fetch();
        createMessage.success($t('common.tips.deleteSuccess'));
      } catch {}
    },
  });
}

// 点击树外面的 批量删除
function handleBatchDelete() {
  const checkedKeys = getTree().getCheckedKeys();
  const checked = getTree().getCheckStrictly()
    ? (checkedKeys as any).checked
    : checkedKeys;

  if (!checked || checked.length <= 0) {
    createMessage.warn($t('common.tips.pleaseSelectTheData'));
    return;
  }
  batchDelete(checked as string[]);
}

defineExpose({ fetch });
</script>
<template>
  <div class="overflow-hidden">
    <div class="mb-2 mt-2">
      <Button
        class="mr-2"
        @click="handleAdd()"
        v-hasAnyPermission="[permCode.add]"
      >
        {{ $t('common.title.addRoot') }}
      </Button>
      <Button
        class="mr-2"
        v-hasAnyPermission="[permCode.delete]"
        @click="handleBatchDelete()"
      >
        {{ $t('common.title.delete') }}
      </Button>
      <Button class="mr-2" @click="fetch()">
        {{ $t('common.redo') }}
      </Button>
    </div>
    <BasicTree
      ref="treeRef"
      :field-names="{ key: 'id', title: 'name' }"
      :action-list="actionList"
      :before-right-click="getRightMenuList"
      :click-row-to-expand="false"
      :loading="treeLoading"
      checkable
      :title="$t('devOperation.system.defArea.table.title')"
      :tree-data="treeData"
      check-strictly
      highlight
      search
      toolbar
      @select="handleSelect"
    />
  </div>
</template>
<style lang="scss" scoped></style>
